package container;

import annotation.Super;
import domain.SuperUser;
import domain.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Map;

/**
 * 依赖查找方式：名称、类型、注解
 * @author jackcfan
 * @date 2021/9/12
 */
public class DependencyLookup {
    BeanFactory beanFactory;

    @Before
    public void before(){
        beanFactory = new ClassPathXmlApplicationContext("dependency-lookup-context.xml");
    }

    /**
     * 根据名称实时查找
     * */
    @Test
    public void lookupRealtime(){
        User user = beanFactory.getBean("user", User.class);
        System.out.println(user);
    }

    /**
     * 通过 ObjectFactory 实现 Bean 的懒加载
     * */
    @Test
    public void lookupLazy(){
        // beanFactory#getBean 获取的不是最终的 Bean
        ObjectFactory<User> objectFactory = beanFactory.getBean("objectFactory",ObjectFactory.class);
        // objectFactory#getObject() 获得真正的 Bean
        System.out.println(objectFactory.getObject());
    }

    /**
     * 根据类型实时查找
     * */
    @Test
    public void lookupByType(){
        User user = beanFactory.getBean(User.class);
        System.out.println(user);
    }

    /**
     * 根据Bean类型查找集合
     * 一个类型可能会有多个对象，此时返回 Map 集合
     * listableBeanFactory.getBeansOfType
     * */
    @Test
    public void lookupCollectionByType(){
        if(beanFactory instanceof ListableBeanFactory){
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory)beanFactory;
            Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);
            System.out.println("根据类型查找集合");
            for(String k : users.keySet()){
                System.out.println(users.get(k));
            }
        }
    }

    /**
     * 根据注解类型查找集合
     * 一个注解类型可能会有多个对象，此时返回 Map 集合
     * listableBeanFactory.getBeansOfType
     * */
    @Test
    public void lookupByAnnotationType(){
        if(beanFactory instanceof ListableBeanFactory){
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory)beanFactory;
            Map<String, SuperUser> superUsers = (Map)listableBeanFactory.getBeansWithAnnotation(Super.class);
            System.out.println("根据注解查找集合");
            for(String k : superUsers.keySet()){
                System.out.println(superUsers.get(k));
            }
        }
    }
}
